#include <fstream>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char* argv[])
{
	if ( argc != 4)
	{
		std::cerr << "obj2lmo braucht das folgende format: " << argv[0] << " map.obj lightmap.obj textureLM.tga" << endl;
		exit(1);
	}
	
	string targetName(argv[1]);
	targetName.replace(targetName.rfind(".obj"), 4, ".lmo");
	string textureLM(argv[3]);
	
	std::ifstream streamMap(argv[1]);
	if ( !streamMap )
	{
		std::cerr << "could not open: " << argv[1] << endl;
		exit(1);
	}
	
	std::ifstream streamLightmap(argv[2]);
	if ( !streamLightmap )
	{
		std::cerr << "could not open: " << argv[2] << endl;
		exit(1);
	}
	
	std::ofstream streamOut(targetName.c_str());
	if ( !streamOut )
	{
		std::cerr << "could not open: " << targetName << endl;
		exit(1);
	}
	
	string lineMap;
	string lineLightmap;
	int countOrigVt = 0;
	
	// write lightmap texture to streamout
	streamOut << "lmo " << textureLM << endl;
	
	// write all lines in streamMap until first vertex texture (vt) to streamout
	while ( streamMap )
	{
		getline(streamMap, lineMap);
		if ( 0 == lineMap.compare(0, 2, "vt" ) )
		     break;
		streamOut << lineMap << endl;
	}
	
	// read all vt's in streamMap and count them. Write them to streamout
	while ( streamMap )
	{
		++countOrigVt;
		streamOut << lineMap << endl;		
		getline(streamMap, lineMap);
		if ( 0 != lineMap.compare(0, 2, "vt") )
			break;
	}
	cout << "vt's in map: " << countOrigVt << endl;
	cout.flush();
	
	// skip all lines in streamLightmap until first vertext texture (vt)
	while ( streamLightmap )
	{
		getline(streamLightmap, lineLightmap);
		if ( 0 == lineLightmap.compare(0, 2, "vt") )
			break;
	}
	
	// read all vt's in streamLightmap and write them to streamout
	while ( streamLightmap )
	{
		streamOut << lineLightmap << endl;
		getline(streamLightmap, lineLightmap);
		if ( 0 != lineLightmap.compare(0, 2, "vt") )
			break;
	}
	
	// read rest of streamLightmap. 
	vector<int> textureIds;
	while ( streamLightmap )
	{
		// if it's a face save the vertextexture id
		if ( 0 == lineLightmap.compare(0, 2, "f ") )	// f v/vt/vn v/vt/vn v/vt/vn
		{
			string::size_type s = 0;
			while ( s != string::npos )
			{
				s = lineLightmap.find("/", s);
				if ( s != string::npos )
				{
					++s;
					string::size_type e = s;
					e = lineLightmap.find("/", e);
					if ( e != string::npos )
					{
						int id = atoi(lineLightmap.substr(s,e-s).c_str());
						textureIds.push_back(id);
						s = e+1;
					}
				}
			}
		}
		getline(streamLightmap, lineLightmap);
	}
	cout << "vt id's in lightmap: " << textureIds.size() << endl;
	cout.flush();
	
	// read rest of streamMap 
	int countLmVt = 0;
	while ( streamMap )
	{
		// if it's a face add the vertextexture id's of the streamLightmap 		
		if ( 0 == lineMap.compare(0, 2, "f ") )
		{
			string::size_type s = lineMap.find(" ", 0);
			// skip first whitespace
			if ( s != string::npos )
			{
				s = lineMap.find(" ", s+1);	
				while ( s != string::npos )
				{
					if ( countLmVt >= textureIds.size() )
					{
						cerr << "not enough texture id's in lightmap" << endl;
						exit(1);
					}
					int id = textureIds[countLmVt] + countOrigVt;
					++countLmVt;					
					ostringstream buf;
					buf << "/" << id;
					lineMap.insert(s, buf.str());
					s = lineMap.find(" ", s);	// skip the already found whitespace, because the inserted number moved it
					s = lineMap.find(" ", s+1);	
				}
				if ( countLmVt >= textureIds.size() )
				{
					cerr << "not enough texture id's in lightmap" << endl;
					exit(1);
				}
				int id = textureIds[countLmVt] + countOrigVt;
				++countLmVt;
				ostringstream buf;
				buf << "/" << id;
				lineMap.append(buf.str());
			}
		}
		streamOut << lineMap << endl;
		getline(streamMap, lineMap);
	}
	
	if ( countLmVt < textureIds.size() )
	{
		cout << "too many texture id's in lightmap" << endl;
	}
	
	cout << "target written to " << targetName << endl;
}
